package com.aube.multiscreen;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.widget.TextView;

import com.aube.R;
import com.aube.StaticApplicationContext;
import com.aube.control.player.AbstractVideoHelper;
import com.aube.control.player.MultiVideoBalanceAdapter;
import com.aube.guide.GuideConstants;
import com.aube.guide.OnGuidePerformedListener;
import com.aube.model.ImageItem;
import com.aube.model.VideoItem;
import com.huyn.baseframework.model.ChannelDetail;
import com.huyn.baseframework.statistics.AubeStatisticEvents;
import com.huyn.baseframework.statistics.AubeStatisticTool;
import com.huyn.baseframework.statistics.EventValuePair;
import com.huyn.baseframework.utils.Constant;
import com.huyn.baseframework.utils.ReflectUtil;
import com.huyn.baseframework.utils.UmengUtils;
import com.huyn.baseframework.utils.Utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public class MultiCameraView extends FrameLayout implements GestureDetector.OnGestureListener, IVideoParentConnector {

    private List<ImageItem> picList;

    private Context context;

    private float mLastMotionY;// 最后点击的点
    private float mLastMotionX;
    private GestureDetector detector;
    public int yMove = 0;// 移动距离
    private Scroller mScroller;
    private final static int TOUCH_STATE_REST = 0;
    private final static int TOUCH_STATE_SCROLLING = 1;
    private int mTouchSlop;
    private int mTouchState = TOUCH_STATE_REST;

    private int MAX_HEIGHT = 0;
    private List<AbstractVideoHelper> mVideoHelperMap;
    private AtomicBoolean mBlockEvent = new AtomicBoolean(true);

    private float startX=-1, startY=-1;
    private long mCurrentProgress = 0;
    private long mDuration = 0;
    private int MAX_DISTANCE = 0;
    private float mLastX=0, mLastY=0;
    private boolean cancelSeek = false;
    private boolean DRAG_STATE= false;
    private boolean SCROLL_MODE = false;
    private boolean FLING_MODE = false;

    private float borderIndexX = 0;
    private List<String> mRightViewGroup = new ArrayList<>();
    private List<String> mPicInPicViewGroup = new ArrayList<>();

    private View mCurrentView=null;
    private float mTransIndexX=0;
    private float mTransIndexY=0;

    private AtomicBoolean mUseScrollerResult = new AtomicBoolean(false);

    private HashMap<String, CameraCardView> mChildViews = new HashMap<>();
    private HashMap<String, String> mVideoIdSet = new HashMap<>();

    private MultiCameraTransitionHelper mHelper;
    public void setVideoHelper(MultiCameraTransitionHelper helper) {
        this.mHelper = helper;
    }

    public MultiCameraView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initContext(context);
    }

    public MultiCameraView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MultiCameraView(Context context) {
        this(context, null);
    }

    private void initContext(Context context) {
        this.context = context;
        mScroller = new Scroller(context);
        detector = new GestureDetector(this);

        final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop()/4;
    }

    public void setSize(int h) {
        MAX_HEIGHT = h;
    }

    public boolean initVideos(List<ImageItem> picList, List<VideoItem> videos, long startTime, boolean play, final IVideoController controller) {
        if (videos == null || videos.size() == 0) {
            return false;
        }
        try {
            this.picList = picList;

            boolean enableSoundSwitcher = false;

            for (int i = 0; i < videos.size(); i++) {
                addVideos(i+1, videos.get(i), startTime, play, controller);
                enableSoundSwitcher |= videos.get(i).enableSound();
            }
            return enableSoundSwitcher;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private void addVideos(int i, VideoItem item, long startTime, boolean play, final IVideoController controller) {
        CameraCardView mSurface = item.isVr() ? new VRCardView(context) : new CameraCardView(context);
        ImageItem imgItem = picList.get(i);
        addView(mSurface, new ViewGroup.LayoutParams(imgItem.width, imgItem.height));

        addToVideoStack(mSurface.play(i, item, startTime+item.delayTime, play, controller));

        mSurface.setIVideoParentConnector(this);
        mSurface.setTag(i+"");
        mSurface.setTag(R.id.card_index, i);

        mSurface.onResume();

        mSurface.initSideCardState();

        mSurface.setTranslationX(imgItem.x);
        mSurface.setTranslationY(imgItem.y);

        mVideoIdSet.put(item.getVideoId(), i+"");
        Utils.Log("ROUTE", "mVideoIdSet...add:" + item.getVideoId() + "/at index:" + i);
    }

    private void addToVideoStack(AbstractVideoHelper helper) {
        if(mVideoHelperMap == null)
            mVideoHelperMap = new ArrayList<>();

        synchronized (mVideoHelperMap) {
            mVideoHelperMap.add(helper);
        }
    }

    public void manageFlingEvent(boolean canFling) {
        mBlockEvent.set(!canFling);
    }

    public void changeDefinition(String des, int type) {
        if(mVideoHelperMap == null)
            return;

        synchronized (mVideoHelperMap) {
            for (AbstractVideoHelper helper : mVideoHelperMap)
                helper.changeDefinition(des, type);
        }
    }

    public void reloadVideoIfNeed() {
        try {
            if (getChildCount() > 0) {
                for (int i = 0; i < getChildCount(); i++) {
                    ((CameraCardView) getChildAt(i)).reloadVideoIfNeed();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 当前视频是否vr视频
     * @param onMajorVideo
     * @return
     */
    public boolean isVrMode(boolean onMajorVideo) {
        if(mHelper != null && mHelper.isMiddleMode())
            return false;
        int index = 0;
        if(!onMajorVideo && mHelper != null)
            index = mHelper.getCurrentIndex();
        View view = findViewWithTag(index+"");
        if(view == null)
            return false;
//        return ((CameraCardView) view).isVr();
        return ((CameraCardView) view).isVr() && ((CameraCardView) view).supportVRMotionMode();
    }

    public int switchDisplayMode() {
        int index = 0;
        if(mHelper != null)
            index = mHelper.getCurrentIndex();
        View view = findViewWithTag(index+"");
        if(view == null || !(view instanceof VRCardView))
            return 0;
        return ((VRCardView) view).switchDisplayMode();
    }

    public int switchInteractiveMode() {
        int index = 0;
        if(mHelper != null)
            index = mHelper.getCurrentIndex();
        View view = findViewWithTag(index+"");
        if(view == null || !(view instanceof VRCardView))
            return 0;
        return ((VRCardView) view).switchInteractiveMode();
    }

    public void doSeek(long current) {
        if(mVideoHelperMap == null)
            return;


        synchronized (mVideoHelperMap) {
            for (AbstractVideoHelper helper : mVideoHelperMap)
                helper.seekTo((int) (current));
        }
    }

    public void start() {
        if(mVideoHelperMap == null)
            return;

        if(MultiVideoBalanceAdapter.getInstance().isLowExperience()) {
            //play current video and pause the rest
            int index = -1;
            if(mHelper != null)
                index = mHelper.getCurrentIndex();
            CameraCardView view = (CameraCardView) findViewWithTag(index+"");
            if(view != null)
                view.startPlayer();
        } else {
            synchronized (mVideoHelperMap) {
                for (AbstractVideoHelper helper : mVideoHelperMap)
                    helper.startPlay();
            }
        }
    }

    public void pause() {
        if(mVideoHelperMap == null)
            return;

        Utils.Log("BALANCE", "**********************start to pause all videos");
        synchronized (mVideoHelperMap) {
            for (AbstractVideoHelper helper : mVideoHelperMap)
                helper.pausePlay();
        }
    }

    public void pauseWhenFreeze() {
        if(mVideoHelperMap == null)
            return;

        if(MultiVideoBalanceAdapter.getInstance().isLowExperience()) {
            //play current video and pause the rest
            int index = -1;
            if(mHelper != null)
                index = mHelper.getCurrentIndex();

            for(int i=0; i<getChildCount(); i++) {
                CameraCardView child = (CameraCardView) getChildAt(i);
                String id = (String) child.getTag();
                if(!id.equalsIgnoreCase(index+"")) {
                    child.suspendPlayer();
                }
            }
        }
    }

    public void updateProgress(long current) {
        if(mVideoHelperMap == null)
            return;

        synchronized (mVideoHelperMap) {
            for (AbstractVideoHelper helper : mVideoHelperMap)
                helper.updateProgress(current);
        }
    }

    public void suspendAllPlayers() {
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).suspendPlayer();
    }

    public void notifyAllPlayers() {
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).startPlayer();
    }

    /**
     * 多镜头消失
     */
    public void onExit() {
        if(mVideoHelperMap != null) {
            Utils.Log("MultiCameraView", "onExit");
            synchronized (mVideoHelperMap) {
                for (AbstractVideoHelper helper : mVideoHelperMap)
                    helper.onDestroy();

                mVideoHelperMap.clear();
                mVideoHelperMap = null;
            }
        }

        int childCount = getChildCount();
        for (int i = 1; i < childCount; i++) {
            CameraCardView view = (CameraCardView) findViewWithTag("" + i);
            if(view != null) {
                view.onDestroy();
                removeView(view);
                mChildViews.remove(i+"");
            }
        }
    }

    public void onDestroy() {
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).onDestroy();

        if(mVideoHelperMap != null) {
            Utils.Log("MultiCameraView", "onDestroy");
            synchronized (mVideoHelperMap) {
                for (AbstractVideoHelper helper : mVideoHelperMap)
                    helper.onDestroy();

                mVideoHelperMap.clear();
                mVideoHelperMap = null;
            }
            removeAllViews();
        }

        setVisibility(View.GONE);
        setAlpha(1);
    }

    public void reset() {
        Utils.Log("MultiCameraView", "reset");
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).onDestroy();

        if(mVideoHelperMap != null) {
            synchronized (mVideoHelperMap) {
                mVideoHelperMap.clear();
                mVideoHelperMap = null;
            }
        }
        removeAllViews();

        startX=-1;
        startY=-1;
        mCurrentProgress = 0;
        mDuration = 0;
        MAX_DISTANCE = 0;
        mLastX=0;
        mLastY=0;
        cancelSeek = false;
        DRAG_STATE= false;
        SCROLL_MODE = false;
        FLING_MODE = false;
        borderIndexX = 0;
        mTransIndexX=0;
        mTransIndexY=0;

        picList = null;
        yMove = 0;// 移动距离
        MAX_HEIGHT = 0;
        mVideoHelperMap = null;
        mBlockEvent.set(true);
        mRightViewGroup.clear();
        mPicInPicViewGroup.clear();
        mCurrentView=null;
        mUseScrollerResult.set(false);
        mChildViews.clear();
        mVideoIdSet.clear();
        mHelper = null;
    }

    public boolean onBackPressed() {
        if(mHelper != null && mHelper.onBack())
            return true;
        return false;
    }

    /******************************************负载均衡逻辑******************************************/

    private String formatFloat(float size) {
        String result = size + "";
        int dotIndex = result.indexOf(".");
        if(dotIndex < 0)
            return result;
        if(dotIndex+3 >= result.length())
            return result;
        return result.substring(0, dotIndex+3);
    }

    public boolean quitWait(AbstractVideoHelper mMajorVideo) {
        if(MultiVideoBalanceAdapter.getInstance().isLowExperience()) {
            mMajorVideo.quitWait();
            for (AbstractVideoHelper helper : mVideoHelperMap) {
                helper.quitWait();
            }
            return true;
        }
        return false;
    }

    /**
     * 负载均衡逻辑
     * 计算整体缓存的平均值,将缓存的比较多的视频限速
     * @param mMajorVideo
     */
    private static final int BUFFER = 5;
    private static final int MAX_GAP = 10;
    private long startStaticsTime = 0;
    public void balanceVideoProgress(AbstractVideoHelper mMajorVideo, TextView txt) {
        if(startStaticsTime <= 0)
            startStaticsTime = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        try {
            sb.append("收到:").append(formatFloat((StaticApplicationContext.receivedDataSize - StaticApplicationContext.RECEIVED_DATA_SIZE)*1f/1024/1024)).append("M\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(mVideoHelperMap != null) {
            synchronized (mVideoHelperMap) {
                if(quitWait(mMajorVideo))
                    return;

                if(mMajorVideo.isPlaying()) {
//                    Utils.Log("BALANCE", "+++++++++++++++++++++++START+++++++++++++++++++++++");
                    int mMainBuffer = mMajorVideo.getCachedBuffer();
//                    Utils.Log("BALANCE", mMajorVideo.getVideoId() + "===" + mMainBuffer);
                    int count = 1;
                    int total = mMainBuffer;

                    boolean hasNegativeBuffer = total <= 0;
                    int minValue = mMainBuffer;

                    sb.append("负载均衡:").append(AbstractVideoHelper.ENABLE_SOCKET_PROXY?"on":"off").append("\r\n");
                    sb.append("m:").append(mMainBuffer).append("\r\n");

                    boolean doStatics = false;
                    long duration = 0;
                    long now = System.currentTimeMillis();
                    if(now >= startStaticsTime + 1000) {
                        duration = now - startStaticsTime;
                        startStaticsTime = 0;
                        doStatics = true;
                    }

                    boolean hasVideoStillPrepareing = false;
                    int i=1;
                    for(AbstractVideoHelper helper : mVideoHelperMap) {
                        if(helper.isPrepared()) {
                            int buffer = helper.getCachedBuffer();
                            if(buffer > 0) {
                                count++;
                                total+= buffer;

                                if(buffer < minValue)
                                    minValue = buffer;
                            } else if(buffer == AbstractVideoHelper.ILLEGAL_BUFFER_RESULT) {
                                hasVideoStillPrepareing = true;
                            } else if(buffer == AbstractVideoHelper.PLAY_END || buffer == AbstractVideoHelper.BUFFER_COMPLETE) {

                            } else {
                                //有时候精度不准确
                                count++;
                                total+= buffer;

                                hasNegativeBuffer = true;
                            }
//                            Utils.Log("BALANCE", helper.getVideoId() + "===" + buffer);
                            sb.append(i).append(":").append(buffer).append("\r\n");
                        } else {
//                            Utils.Log("BALANCE", helper.getVideoId() + "===not play");
                            sb.append(i).append(":preparing").append("\r\n");
                            hasVideoStillPrepareing = true;
                        }
                        i++;
                    }

                    sb.append("--------------------").append("\r\n");
                    int average = hasVideoStillPrepareing ? 0 : total/count;

//                    Utils.Log("BALANCE", ".........................." + average);

                    boolean makeWaiting = true;
                    if(mMainBuffer < average && !hasVideoStillPrepareing) {
                        if(hasNegativeBuffer && mMainBuffer > 0) {
                            makeWaiting = true;
                        } else {
                            makeWaiting = false;
                        }
                    } else {
                        if(Math.abs(mMainBuffer - average) <= BUFFER && !hasVideoStillPrepareing && !hasNegativeBuffer) {
                            if(mMainBuffer > 0 && mMainBuffer > minValue + MAX_GAP) {
                                makeWaiting = true;
                            } else {
                                makeWaiting = false;
                            }
                        } else {
                            makeWaiting = true;
                        }
                    }

                    manageProxyBalance(mMajorVideo, sb, makeWaiting, "m", duration, doStatics);

                    i=1;
                    for(AbstractVideoHelper helper : mVideoHelperMap) {
                        if(helper.isPrepared()) {
                            int buffer = helper.getCachedBuffer();
                            if(buffer < average && !hasVideoStillPrepareing) {
                                if(hasNegativeBuffer && buffer > 0) {
                                    makeWaiting = true;
                                } else {
                                    makeWaiting = false;
                                }
                            } else if(buffer <= 0 && buffer != AbstractVideoHelper.PLAY_END) {
                                makeWaiting = false;
                            } else if(mMainBuffer == AbstractVideoHelper.PLAY_END) {
                                makeWaiting = false;
                            } else {
                                if(Math.abs(buffer - average) <= BUFFER && !hasVideoStillPrepareing && !hasNegativeBuffer) {
                                    if(buffer > 0 && buffer > minValue + MAX_GAP) {
                                        makeWaiting = true;
                                    } else {
                                        makeWaiting = false;
                                    }
                                } else {
                                    makeWaiting = true;
                                }
                            }
                        } else {
                            makeWaiting = false;
                        }

                        manageProxyBalance(helper, sb, makeWaiting, i, duration, doStatics);
                        i++;
                    }

//                    Utils.Log("BALANCE", "+++++++++++++++++++++++END+++++++++++++++++++++++");
                }
            }
        } else {
            mMajorVideo.quitWait();
        }

        if(Constant.DEBUG)
            txt.setText(sb.toString());
    }

    private void manageProxyBalance(AbstractVideoHelper helper, StringBuffer sb, boolean makeWaiting, int i, long mDuration, boolean doStatics) {
        manageProxyBalance(helper, sb, makeWaiting, i+"", mDuration, doStatics);
    }

    private HashMap<String, String> speedMap = new HashMap<>();
    private void manageProxyBalance(AbstractVideoHelper helper, StringBuffer sb, boolean makeWaiting, String i, long mDuration, boolean doStatics) {
        String end = "\r\n";
        if(doStatics) {
            end = " " + formatFloat(helper.dataLoaded*1f*1000/mDuration/1024) + "kb/s";
            helper.dataLoaded = 0;
            speedMap.put(i, end);
        } else {
            if(speedMap.containsKey(i))
                end = speedMap.get(i);
        }
        end += (helper.isProxyWaiting ? "_W" : "_L") + "\r\n";
        if(makeWaiting) {
            helper.makeAWait();
            sb.append(i).append(":").append("waiting").append(end);
//            Utils.Log("BALANCE", helper.getVideoId() + "---wait");
        } else {
            helper.quitWait();
            sb.append(i).append(":").append("loading").append(end);
//            Utils.Log("BALANCE", helper.getVideoId() + "---loading");
        }
    }

    /******************************************负载均衡逻辑******************************************/

    public void onResume() {
        Utils.Log("multicameraview onresume==============================" + getChildCount());
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).onResume();
    }

    public void onPause() {
        for(int i=0; i<getChildCount(); i++)
            ((CameraCardView) getChildAt(i)).onPause();
    }

    private boolean isInCurrentView(View view, float x, float y) {
        if(view == null)
            return false;
        int[] locations = new int[2];
        view.getLocationOnScreen(locations);
        RectF rect = new RectF(locations[0], locations[1], locations[0] + view.getWidth(), locations[1] + view.getHeight());
        return rect.contains(x, y);
//        Rect reLoc = new Rect();
//        view.getHitRect(reLoc);
//        return reLoc.contains((int)x, (int)y);
    }

    private boolean consumeTouchEvent(View view) {
        return ((CameraCardView) view).consumeTouchEvent();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final float y = ev.getY();
        final float x = ev.getX();
        FLING_MODE = false;
//        if(getChildCount() == 1)
//            return false;
        if(borderIndexX == 0 && mRightViewGroup.size() > 0)
            borderIndexX = getChildAt(Integer.parseInt(mRightViewGroup.get(0))).getTranslationX();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastMotionY = y;
                mLastMotionX = x;
                mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
                        : TOUCH_STATE_SCROLLING;
                break;
            case MotionEvent.ACTION_MOVE:
                if(mHelper != null && mHelper.isAnimRunning())
                    break;
//                if(x <= borderIndexX && borderIndexX > 0)
//                    break;

                if(mBlockEvent.get())
                    break;

                final int yDiff = (int) Math.abs(y - mLastMotionY);
                final int xDiff = (int) Math.abs(x - mLastMotionX);
                boolean yMoved = yDiff > mTouchSlop;
                boolean xMoved = xDiff > mTouchSlop;
                // 判断是否是移动
                if(!yMoved && !xMoved)
                    break;

                if(mHelper != null) {
                    mCurrentProgress = mHelper.getCurrentProgress();
                    mDuration = mHelper.getDuration();
                    MAX_DISTANCE = getWidth() / 2;
                }

                mCurrentView = null;
                View mView = null;
                boolean inRight = false;
                SCROLL_MODE = false;

                for(int i=getChildCount()-1; i>=0; i--) {
                    View view = getChildAt(i);
                    String tag = (String) view.getTag();
                    if(isInCurrentView(view, mLastMotionX, mLastMotionY)) {
                        if(isInPic(tag)) {
                            mView = view;
                        } else if(isInSidePic(tag)) {
                            inRight = true;
                            mView = view;
                        } else {
                            if(consumeTouchEvent(view))
                                return false;
                        }
                        break;
                    }
                }

                if(mView == null) {
                    //在边界处才有效
                    if(Math.abs(getWidth() - x) < 200) {
                        FLING_MODE = true;
                        mTouchState = TOUCH_STATE_SCROLLING;
                    } else if(xDiff >= 6 * mTouchSlop) {
                        mTouchState = TOUCH_STATE_SCROLLING;
                    }
                    break;
                } else {
                    if(inRight) {
//                        if(xDiff > yDiff && xMoved) {
                        if (getHeight() >= MAX_HEIGHT) {
                            mTouchState = TOUCH_STATE_SCROLLING;
                            DRAG_STATE = true;

                            mCurrentView = mView;
                            mTransIndexX = mCurrentView.getTranslationX();
                            mTransIndexY = mCurrentView.getTranslationY();

                            mCurrentView.bringToFront();
                        } else if(xDiff < yDiff && yMoved) {
                            mTouchState = TOUCH_STATE_SCROLLING;
                            SCROLL_MODE = true;
                        }
                    } else {
                        mTouchState = TOUCH_STATE_SCROLLING;
                        DRAG_STATE = true;

                        mCurrentView = mView;
                        mTransIndexX = mCurrentView.getTranslationX();
                        mTransIndexY = mCurrentView.getTranslationY();

                        mCurrentView.bringToFront();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                mTouchState = TOUCH_STATE_REST;
                break;
        }
        return mTouchState != TOUCH_STATE_REST;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if(mBlockEvent.get())
            return super.onTouchEvent(ev);

        final float y = ev.getY();
        final float x = ev.getX();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.forceFinished(true);
                    yMove = mScroller.getCurrY();
                }
                mLastMotionY = y;
                mLastMotionX = x;
                yMove = 0;
                startX = x;
                startY = y;

                if(DRAG_STATE) {
                } else if(SCROLL_MODE) {
                } else {
                    if (!FLING_MODE) {
                        //快进快退控制
                        if (mDuration > 0) {
                            if (mHelper != null) {
                                mHelper.onStartTrackingTouch();
                            }
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (startX < 0 || startY < 0) {
                    startX = x;
                    startY = y;
                }

                if(mLastY == 0 || mLastX == 0) {
                    mLastX = x;
                    mLastY = y;
                }
                cancelSeek = false;

                if(DRAG_STATE) {
                    doViewDrag(x, y);
                } else if(SCROLL_MODE) {
                    if (ev.getPointerCount() == 1) {
                        // 随手指 拖动的代码
//                        float deltaY = y - mLastMotionY;
//                        mLastMotionY = y;
//                        yMove += deltaY;
                        yMove = (int) (y - startY);

                        relayout();
                    }
                } else {
                    if(!FLING_MODE) {
                        //快进快退控制
                        if (mDuration > 0 && MAX_DISTANCE > 0) {
                            try {
                                float deltaX = x - startX;
                                if(mHelper != null) {
                                    if(!cancelSeek) {
                                        if (Math.abs(x - mLastX) < Math.abs(y - mLastY) && Math.abs(y - mLastY) >= mTouchSlop) {
                                            cancelSeek = true;
                                        }

                                        //消灭卡顿
                                        if (Math.abs(deltaX) > 0) {
                                            float currentRatio = mCurrentProgress * 1f / mDuration;
                                            float flingRatio = deltaX / MAX_DISTANCE;
                                            float ratio = currentRatio + flingRatio;
                                            mHelper.manageProgress(deltaX > 0, ratio > 1 ? 1 : (ratio < 0 ? 0 : ratio), false);
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

//                mLastX = x;
//                mLastY = y;
                break;
            case MotionEvent.ACTION_UP:
                if(DRAG_STATE) {
                    animBack();
                } else if(SCROLL_MODE) {
                    if (getHeight() < MAX_HEIGHT) {
                        int min = (int) getFirstViewTranslationY();
                        int max = (int) getLastViewTranslationY();

                        if(min > mHelper.getGap())
                            animPullView(yMove, yMove - min + mHelper.getGap());
                        else if(max < getHeight() - mHelper.getGap() - mHelper.getPicInSideHeight())
                            animPullView(yMove, yMove - (max + mHelper.getGap() + mHelper.getPicInSideHeight() - getHeight()));
                        else
                            updateCoordinates();
                    } else {
                        animPullView(yMove, 0);
                    }
                } else {
                    if(!FLING_MODE) {
                        //快进快退控制
                        if (mDuration > 0 && MAX_DISTANCE > 0) {
                            try {
                                float deltaX = x - startX;
                                if (mHelper != null) {
                                    if(cancelSeek) {
                                        //取消
                                        mHelper.cancelSeek();
                                    } else if(Math.abs(deltaX) > 0) {
                                        float currentRatio = mCurrentProgress * 1f / mDuration;
                                        float flingRatio = deltaX / MAX_DISTANCE;
                                        float ratio = currentRatio + flingRatio;
                                        mHelper.manageProgress(deltaX > 0, ratio > 1 ? 1 : (ratio < 0 ? 0 : ratio), true);
                                    }

                                    mHelper.endUpdateProgress();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                mTouchState = TOUCH_STATE_REST;
                startY = startX = -1;
                mLastX = mLastY = 0;
                cancelSeek = false;
                break;
        }
        return this.detector.onTouchEvent(ev);
    }

    private float getFirstViewTranslationY() {
        float min = getHeight();
        for(String id : mRightViewGroup) {
            float x = findViewWithTag(id).getTranslationY();
            if(x < min)
                min = x;
        }
        return min;
    }

    private float getLastViewTranslationY() {
        float max = 0;
        for(String id : mRightViewGroup) {
            float x = findViewWithTag(id).getTranslationY();
            if(x > max)
                max = x;
        }
        return max;
    }

    public void removeViews(HashMap<String, String> videos) {
        if(videos != null && videos.size() > 0) {
            Iterator<String> iterator = videos.keySet().iterator();
            while (iterator.hasNext()) {
                String id = iterator.next();
                CameraCardView view = (CameraCardView) findViewWithTag(id);
                view.stopPlayer();
                mChildViews.remove(id);
            }
        }
    }

    public void removeView(String id) {
        CameraCardView view = (CameraCardView) findViewWithTag(id);
        view.stopPlayer();
        mChildViews.remove(id);
    }

    public int getVisibleChildCount() {
        return mChildViews.size();
    }

    public CameraCardView getVisibleChild(String key) {
        return mChildViews.get(key);
    }

    public HashMap<String, CameraCardView> getVisibleChildren() {
        return mChildViews;
    }

    public boolean isChildVisible(int id) {
        return mChildViews.containsKey(id + "");
    }

    public void setChildVisible(String id, long current) {
        CameraCardView view = (CameraCardView) findViewWithTag(id);
        view.notifyPlayer(current);
        mChildViews.put(id, view);
        Utils.Log("ROUTE", "add to mChildViews:" + id + "++++++++setChildVisible++++++size:" + mChildViews.size());

        addToSideSet(id);
    }

    public void setChildVisible(HashMap<String, VideoItem> videoIds, long current) {
        if(videoIds == null || videoIds.size() == 0)
            return;
        Iterator<String> iterator = videoIds.keySet().iterator();
        while (iterator.hasNext()) {
            setChildVisible(mVideoIdSet.get(iterator.next()), current);
        }
    }

    public void addToChildrenGroup(String id, CameraCardView view) {
        mChildViews.put(id, view);
        Utils.Log("ROUTE", "add to mChildViews:" + id + "++++++++addToChildrenGroup++++++size:" + mChildViews.size());
    }

//    public boolean hasChanged(HashMap<String, String> videos) {
//        Iterator<String> videoNos = videos.keySet().iterator();
//        while (videoNos.hasNext()) {
//            String id = mVideoIdSet.get(videoNos.next());
//            if(findViewWithTag(id).getVisibility() != View.VISIBLE)
//                return true;
//        }
//        return false;
//    }

    public Iterator<String> idIterator(HashMap<String, VideoItem> videos) {
        HashMap<String, String> idMaps = new HashMap<>();

        if(videos != null) {
            Iterator<String> noIterator = videos.keySet().iterator();
            while (noIterator.hasNext()) {
                idMaps.put(mVideoIdSet.get(noIterator.next()), "");
            }
        }

        return idMaps.keySet().iterator();
    }

    public Iterator<Map.Entry<String, VideoItem>> generateVideoIterator(HashMap<String, VideoItem> videos) {
        HashMap<String, VideoItem> idMaps = new HashMap<>();

        if(videos != null) {
            Iterator<String> noIterator = videos.keySet().iterator();
            while (noIterator.hasNext()) {
                String value = noIterator.next();
                idMaps.put(mVideoIdSet.get(value), videos.get(value));
            }
        }

        return idMaps.entrySet().iterator();
    }

    public HashMap<String, String> generateVideoMap(HashMap<String, VideoItem> videos) {
        HashMap<String, String> indexIdMaps = new HashMap<>();

        if(videos != null) {
            Iterator<String> noIterator = videos.keySet().iterator();
            while (noIterator.hasNext()) {
                String value = noIterator.next();
                Utils.Log("ROUTE", "generateVideoMap...add:" + value + " at mVideoIdSet:" + mVideoIdSet.get(value));
                indexIdMaps.put(mVideoIdSet.get(value), value);
            }
        }

        return indexIdMaps;
    }

    public String getVideoIdByIndex(String index) {
        return ((CameraCardView) findViewWithTag(index)).getVideoId();
    }

    public void bringLeftToFront(int ignoreThis) {
        for(int i=0; i<getChildCount(); i++) {
            if(i != ignoreThis) {
                View view = findViewWithTag(i + "");
                view.bringToFront();
            }
        }
    }

    /**
     * 获取接下来多镜头的显示状况, 值为true表示要加入, 值为false表示要移除
     * @param videos
     * @return
     */
    public HashMap<String, Boolean> manageVideos(HashMap<String, VideoItem> videos) {
        HashMap<String, Boolean> videoState = new HashMap<>();

        Iterator<String> nos = videos.keySet().iterator();
        while (nos.hasNext()) {
            String no = nos.next();
            String id = mVideoIdSet.get(no);
            //Utils.Log("ROUTE", "manageVideos...add:" + id + "/" + no);
            videoState.put(id, true);
        }

        for(int i=1; i<getChildCount(); i++) {
            String id = i+"";
            if(mChildViews.containsKey(id)) {
                //Utils.Log("ROUTE", "manageVideos...containsKey:" + id);
                if(!videoState.containsKey(id)) {
                    videoState.put(id, false);
                    //Utils.Log("ROUTE", "manageVideos...make:" + id + " false");
                } else {
                    videoState.remove(id);
                    //Utils.Log("ROUTE", "manageVideos...remove:" + id);
                }
            } else {
                //Utils.Log("ROUTE", "manageVideos...not containsKey:" + id);
            }
        }
        return videoState;
    }

    /**
     * 从画中画队列移除对应数据
     * @param id
     */
    public void removeFromPicInPicSet(String id) {
        int index = 0;
        for(String s : mPicInPicViewGroup) {
            if(s.equalsIgnoreCase(id)) {
                mPicInPicViewGroup.remove(index);
                return;
            }
            index++;
        }
    }

    public void addToPicInPicSet(String id) {
        mPicInPicViewGroup.add(id);
    }

    /**
     * 添加到右侧队列
     * @param id
     */
    public void addToSideSet(String id) {
        if(mRightViewGroup.contains(id))
            return;
        mRightViewGroup.add(id);
    }

    public void removeFromSideSet(String id) {
        int index = 0;
        for(String s : mRightViewGroup) {
            if(s.equalsIgnoreCase(id)) {
                mRightViewGroup.remove(index);
                return;
            }
            index++;
        }
    }

    public List<String> getRightSideViews() {
        if(mCurrentView == null)
            return mRightViewGroup;
        String tag = (String) mCurrentView.getTag();
        mRightViewGroup.remove(tag);
        return mRightViewGroup;
    }

    public boolean isInSidePic(String id) {
        if(mRightViewGroup == null)
            return false;
        return mRightViewGroup.contains(id);
    }

    public int getRightSidePicSize() {
        if(mRightViewGroup == null)
            return 0;
        return mRightViewGroup.size();
    }

    public boolean isInPic(int index) {
        if(mPicInPicViewGroup == null)
            return false;
        return mPicInPicViewGroup.contains(index+"");
    }

    public boolean isInPic(String index) {
        if(mPicInPicViewGroup == null)
            return false;
        return mPicInPicViewGroup.contains(index);
    }

    public int getPicInPicSize() {
        if(mPicInPicViewGroup == null)
            return 0;
        return mPicInPicViewGroup.size();
    }

    public String getPicId(int index) {
        return mPicInPicViewGroup.get(index);
    }

    /**
     * 属性动画更新绘制样式
     * @param picList
     */
    public void updatePics(List<ImageItem> picList) {
        this.picList = picList;

        int i=0;
        for(ImageItem item : picList) {
            View child = getChildAt(i);
            ViewGroup.LayoutParams param = child.getLayoutParams();
            param.width = item.width;
            param.height = item.height;
            child.setLayoutParams(param);
            child.setTranslationX(item.x);
            child.setTranslationY(item.y);
            i++;
        }
    }

    public void swap(int newIndex, int currentIndex) {
        mRightViewGroup.remove(newIndex + "");
        mRightViewGroup.add(currentIndex + "");

        swapDisplayState(newIndex, currentIndex, false);
    }

    /**
     * 在中屏模式下执行
     */
    private void animBack() {
//        if(mHelper == null || mHelper.isFullScreen())
//            return;
        if(mCurrentView != null) {
            int standX = mHelper.getDragDividerX();
            if(standX <= 0)
                return;

            int picInPicWidth = mHelper.getPicInPicWidth();
            if(picInPicWidth <= 0)
                return;

            locateView(standX, picInPicWidth);
        }
    }

    private void doReverse(final float currentX, final float currentY, boolean picInPic) {
        if(mHelper.isAnimRunning())
            return;
        mHelper.toggleAnimState(true);

        //做一个弹性回位,同时要改变size
        final int startW = mCurrentView.getWidth();
        final int startH = mCurrentView.getHeight();

        final int targetW = picInPic ? mHelper.getPicInPicWidth() : mHelper.getPicInSideWidth();
        final int targetH = picInPic ? mHelper.getPicInPicHeight() : mHelper.getPicInSideHeight();

        ValueAnimator anim = ValueAnimator.ofFloat(1, 0);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();

                ViewGroup.LayoutParams param = mCurrentView.getLayoutParams();
                param.width = (int) (targetW + value * (startW - targetW));
                param.height = (int) (targetH + value * (startH - targetH));
                mCurrentView.setLayoutParams(param);
                mCurrentView.setTranslationX((currentX - mTransIndexX) * value + mTransIndexX);
                mCurrentView.setTranslationY((currentY - mTransIndexY) * value + mTransIndexY);
            }
        });
        anim.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                DRAG_STATE = false;
                mCurrentView = null;

                mHelper.toggleAnimState(false);
            }

        });
        anim.setDuration(400);
        anim.start();
    }

    private void toStandardPosition(final String tag, final ImageItem end, final float startX, final float startY, final float targetX, final float targetY) {
        if(mHelper.isAnimRunning())
            return;
        mHelper.toggleAnimState(true);
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();

                mCurrentView.setTranslationX((targetX - startX) * value + startX);
                mCurrentView.setTranslationY((targetY - startY) * value + startY);
            }
        });
        anim.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                mHelper.toggleAnimState(false);
                mHelper.updateImageItemByIndex(tag, new ImageItem(end.width, end.height, targetX, targetY));

                mCurrentView = null;
            }

        });
        anim.setDuration(400);
        anim.start();
    }

    private void locateView(int standX, int picInPicWidth) {
        final String tag = (String) mCurrentView.getTag();
        final float currentX = mCurrentView.getTranslationX();
        final float currentY = mCurrentView.getTranslationY();

        //要保存view的size

        if(isInPic(tag)) {
            if(currentX <= standX - picInPicWidth) {
                ImageItem end = new ImageItem(mCurrentView.getWidth(), mCurrentView.getHeight(), currentX, currentY);
                mHelper.updateImageItemByIndex(tag, end);
                DRAG_STATE = false;

                //还要判断左/上/下边界
                if(currentX < mHelper.getLeft() || currentY < mHelper.getTop() || currentY > mHelper.getBottom() - mCurrentView.getHeight()) {
                    float targetX = currentX < mHelper.getLeft() ? mHelper.getLeft() : currentX;
                    float targetY = currentY < mHelper.getTop() ? mHelper.getTop() : (currentY > (mHelper.getBottom() - mCurrentView.getHeight()) ? (mHelper.getBottom()-mCurrentView.getHeight()) : currentY);
                    toStandardPosition(tag, end, currentX, currentY, targetX, targetY);
                } else {
                    mCurrentView = null;
                }
            } else if(currentX <= standX - picInPicWidth/2) {
//                doReverse(currentX, currentY, true);
                float targetY = currentY < mHelper.getTop() ? mHelper.getTop() : ((currentY > mHelper.getBottom() - mHelper.getPicInPicHeight()) ? (mHelper.getBottom() - mHelper.getPicInPicHeight()) : currentY);
                ImageItem end = new ImageItem(mCurrentView.getWidth(), mCurrentView.getHeight(), currentX, currentY);
                ImageItem target = new ImageItem(picInPicWidth, mHelper.getPicInPicHeight(), standX - picInPicWidth, targetY);
                mHelper.toStandardPosition(tag, end, target, new IAnimEndListener() {
                    @Override
                    public void animEnd() {
                        mCurrentView = null;
                    }
                });
            } else {
                mHelper.dragFromMainPic(mCurrentView, tag, currentX, currentY, new IAnimEndListener() {
                    @Override
                    public void animEnd() {
                        DRAG_STATE = false;
//                        ((CameraCardView) mCurrentView).hideTitle(true);

                        ((CameraCardView) mCurrentView).manageAudioAndMask(true);

                        mCurrentView = null;

                        reCalculateRightSizeHeight();
                    }
                });
            }
        } else {
            if(currentX <= standX - picInPicWidth/2) {
                ImageItem end = new ImageItem(mCurrentView.getWidth(), mCurrentView.getHeight(), currentX, currentY);
                mHelper.updateImageItemByIndex(tag, end);

                String videoId = ((CameraCardView) mCurrentView).getVideoId();

                ((CameraCardView) mCurrentView).hideTitle(true);
                mRightViewGroup.remove(tag);
                mPicInPicViewGroup.add(tag);
                DRAG_STATE = false;

                ChannelDetail channelDetail = mHelper.getChannelDetail();
                UmengUtils.reportUmengEvent(context, UmengUtils.DRAG_VIDEO_TO_MIDDLE, UmengUtils.appendLabels(channelDetail.videoid, channelDetail.videoTitle, ((CameraCardView) mCurrentView).getTitle()));

                //多镜头永远在最上
//                mCurrentView.bringToFront();
//                changeChildOrder(mCurrentView, getChildCount() - 1);

                reCalculateRightSizeHeight();

                boolean animate = false;
                //还要判断左/上/下边界
                if (currentX < mHelper.getLeft() || currentY < mHelper.getTop() || currentY > mHelper.getBottom() - mCurrentView.getHeight()) {
                    float targetX = currentX < mHelper.getLeft() ? mHelper.getLeft() : ((currentX <= standX - picInPicWidth) ? currentX : (standX - picInPicWidth));
                    float targetY = currentY < mHelper.getTop() ? mHelper.getTop() : (currentY > (mHelper.getBottom() - mCurrentView.getHeight()) ? (mHelper.getBottom() - mHelper.getPicInPicHeight()) : currentY);
                    ImageItem target = new ImageItem(picInPicWidth, mHelper.getPicInPicHeight(), targetX, targetY);
                    mHelper.toStandardPosition(tag, end, target, new IAnimEndListener() {
                        @Override
                        public void animEnd() {
                            ((CameraCardView) mCurrentView).manageAudioAndMask(false);
                            mCurrentView = null;

                            if(getRightSidePicSize() == 0)
                                performCurrentVideoZoomClick();
                        }
                    });
                } else if(currentX > standX - picInPicWidth) {
                    ImageItem target = new ImageItem(picInPicWidth, mHelper.getPicInPicHeight(), standX - picInPicWidth, currentY);
                    mHelper.toStandardPosition(tag, end, target, new IAnimEndListener() {
                        @Override
                        public void animEnd() {
                            ((CameraCardView) mCurrentView).manageAudioAndMask(false);
                            mCurrentView = null;

                            if(getRightSidePicSize() == 0)
                                performCurrentVideoZoomClick();
                        }
                    });
                } else {
                    ((CameraCardView) mCurrentView).manageAudioAndMask(false);
                    mCurrentView = null;

                    if(getRightSidePicSize() == 0)
                        performCurrentVideoZoomClick();
                    else
                        animate = true;
                }

                mHelper.animUpSideViews(animate);

                GuideConstants.dragGuidePerformed(getContext());

                //短暂的显示工具条
                mHelper.showTools(2000);

                //画中画事件统计
                AubeStatisticTool.getInstance(context).report(AubeStatisticEvents.MULTIVIDEO_PIP,
                        AubeStatisticEvents.formatValues(new EventValuePair("vid", channelDetail.videoid), new EventValuePair("target", videoId)));
            } else {
                doReverse(currentX, currentY, false);
            }
        }
    }

    private void performCurrentVideoZoomClick() {
        View view = findViewWithTag(mHelper.getCurrentIndex() + "");
        if(view != null)
            ((CameraCardView) view).switchViewSize();
    }

    //重新计算高度右侧高度
    private void reCalculateRightSizeHeight() {
        setSize(mHelper.getRightSideHeight(getRightSidePicSize()));
    }

    public void resizeView(ImageItem item) {
        if(mCurrentView == null)
            return;
        ViewGroup.LayoutParams param = mCurrentView.getLayoutParams();
        param.width = item.width;
        param.height = item.height;
        mCurrentView.setLayoutParams(param);
        mCurrentView.setTranslationX(item.x);
        mCurrentView.setTranslationY(item.y);
    }

    /**
     * 还需要动态改表size
     * @param x
     * @param y
     */
    private void doViewDrag(float x, float y) {
        if(mCurrentView == null)
            return;
        float currentX = mTransIndexX + x - startX;
        float currentY = mTransIndexY + y - startY;

        Utils.Log("SYSOUT", "mTransIndexX:" + mTransIndexX + "_startx:" + startX + "___deltaX:" + x);
        Utils.Log("SYSOUT", "mTransIndexY:" + mTransIndexY + "_starty:" + startY + "___deltaY:" + y);

        mCurrentView.setTranslationX(currentX);
        mCurrentView.setTranslationY(currentY);

        int standX = mHelper.getDragDividerX();
        if(standX <= 0)
            return;
        int picInPicWidth = mHelper.getPicInPicWidth();
        if(picInPicWidth <= 0)
            return;
        int distance = mHelper.getStandardDistance();
        if(distance <= 0)
            return;
        String tag = (String) mCurrentView.getTag();

        //跟随位置改变size
        if(isInPic(tag)) {
            if(currentX <= standX - picInPicWidth) {
                //size不变
            } else {
                float ratio = 0;
                if(currentX >= standX-picInPicWidth) {
                    ratio = Math.abs(standX - picInPicWidth - currentX) * 1.0f / distance;
                    ratio = ratio >= 1 ? 1f : ratio;
                }
                mHelper.resizeView(ratio, mCurrentView);
            }
        } else {
            float ratio = 0;
            if(currentX >= standX-picInPicWidth) {
                ratio = Math.abs(standX - picInPicWidth - currentX) * 1.0f / distance;
                ratio = ratio >= 1 ? 1f : ratio;
            }
            mHelper.resizeView(ratio, mCurrentView);
        }
    }

    private void relayout() {
        for(String index : mRightViewGroup) {
            findViewWithTag(index).setTranslationY(mHelper.getImageItem(Integer.parseInt(index)).y + yMove);
        }
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            yMove = mScroller.getCurrY();
            invalidate();
            relayout();
        } else {
            if(mUseScrollerResult.get()) {
                updateCoordinates();

                mUseScrollerResult.set(false);
            }
        }
    }

    /**
     * 更新子视频的位置,更新坐标,当右侧小视频过多,屏幕显示不下需要上下拖动的时候
     */
    private void updateCoordinates() {
        for(String id : getRightSideViews()) {
            mHelper.updateImageItemByIndex(id, findViewWithTag(id).getTranslationY());
        }
    }

    private void animPullView(int from, int end) {
        mUseScrollerResult.set(true);
        mScroller.startScroll(0, from, 0, end - from, 500);
        invalidate();
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if(!FLING_MODE)
            return false;
        if(Math.abs(velocityX) > Math.abs(velocityY)) {
            if(velocityX < 0 && mHelper != null && mHelper.canFling()) {
                mHelper.reverseFromFullScreen(false);
//            } else if(velocityX > 0 && mHelper != null && mHelper.canFling()) {
//                mHelper.toFullScreen();
            }
        }
        return false;
    }

    public void hideAll(int index1, int index2) {
        ((CameraCardView) findViewWithTag(index1 + "")).hideAll();
        ((CameraCardView) findViewWithTag(index2 + "")).hideAll();
    }

    /**
     * 交换显示样式
     * @param targetIndex 要放大的view
     * @param lastIndex 要缩小的view
     */
    public void swapDisplayState(int targetIndex, int lastIndex, boolean showClose) {
        if(targetIndex == lastIndex)
            return;
        CameraCardView targetView = (CameraCardView) findViewWithTag(targetIndex + "");
        CameraCardView lastView = (CameraCardView) findViewWithTag(lastIndex + "");
        Utils.Log("VOICE", "...................swapDisplayState");
        if(!mHelper.isFullScreen()) {
            targetView.showTitle();
            targetView.managePadding(true, false);
        } else {
            targetView.hideAll();
            targetView.managePadding(false, false);
        }

        /**切换声音*/
        if(!targetView.isSoundOn()) {
            lastView.manageSound(false);
            targetView.manageSound(true);
        }

        lastView.hideTitle(showClose);
        lastView.managePadding(true, true);

        //改变voice的位置
        lastView.manageAudioAndMask(!isInPic(lastIndex));

        //交换播放模式
        if(MultiVideoBalanceAdapter.getInstance().isLowExperience() && mHelper.isPlaying()) {
            targetView.startPlayer();
            targetView.seekTo((int) mHelper.getCurrentProgress() + 2000);//跟着已经播放的总时间往前走, 多加一点防止视频后退到关键帧
            lastView.suspendPlayer();
        }
    }

    public void showDes() {
        if(mPicInPicViewGroup == null)
            return;

        for(String s : mPicInPicViewGroup) {
            ((CameraCardView) findViewWithTag(s)).manageStateInPIP(true);
        }
    }

    public void hideDes() {
        if(mPicInPicViewGroup == null)
            return;

        for(String s : mPicInPicViewGroup) {
            ((CameraCardView) findViewWithTag(s)).manageStateInPIP(false);
        }
    }

    public void clear() {
        mRightViewGroup.clear();
        mPicInPicViewGroup.clear();
    }

    public void relaodViewStack(int selectedIndex, boolean doAnim) {
        View view0 = getChildAt(0);
        View view1 = findViewWithTag(selectedIndex+"");

        int index = -1;

        for(int i=0; i<getChildCount(); i++) {
            String tag = (String) getChildAt(i).getTag();
            if(tag.equalsIgnoreCase(""+selectedIndex)) {
                index = i;
                break;
            }
        }

        if(view1.getParent() != null) {
            changeChildOrder(view1, 0);
        }
        if(view0.getParent() != null) {
            if(doAnim)
                view0.setAlpha(0);
            changeChildOrder(view0, index);

            if(doAnim) {
                //做一个渐变
                Animator anim = ObjectAnimator.ofFloat(view0, "alpha", 0, 1);
                anim.setDuration(300);
                anim.start();
            }
        }
    }

    /**
     * 通过反射改变view的层级关系
     * @param child
     * @param targetIndex
     */
    private void changeChildOrder(View child, int targetIndex) {
        int index = indexOfChild(child);
        if (index >= 0) {
            ReflectUtil.invoke(this, "removeFromArray", new Class[]{int.class}, new Object[]{index});
            ReflectUtil.invoke(this, "addInArray", new Class[]{View.class, int.class}, new Object[]{child, targetIndex});
            ReflectUtil.setValueByInflect(child, "mParent", this);

            requestLayout();
            invalidate();
        }
    }

    @Override
    public boolean isInPIPMode(String id) {
        if(mPicInPicViewGroup != null)
            return mPicInPicViewGroup.contains(id);
        return false;
    }

    public void showClickGuide(CameraCardView target) {
        boolean showSwitchGuide = GuideConstants.showSwitchGuide((Activity) context, target, new OnGuidePerformedListener() {
            @Override
            public void onPerformed(String id) {
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        showDragGuide();
                    }
                }, 2000);
            }
        });
        if(!showSwitchGuide)
            showDragGuide();
    }

    public void showSwitchGuide() {
        try {
//            int size = getChildCount();
//            CameraCardView target = (CameraCardView) findViewWithTag("" + size / 2);
//            target.enableClickGuide();
            CameraCardView target = null;
            int minSpace = 1000;
            int middleHeight = getHeight()/2;
            for(int i=0; i<mRightViewGroup.size(); i++) {
                String tag = mRightViewGroup.get(i);
                if("0".equalsIgnoreCase(tag))
                    continue;
                CameraCardView item = (CameraCardView) findViewWithTag(tag);
                if(item == null)
                    continue;
                int[] loc = new int[2];
                item.getLocationInWindow(loc);
                int delta = Math.abs(loc[1] + item.getHeight()/2 - middleHeight);
                if(delta < minSpace) {
                    minSpace = delta;
                    target = item;
                }
            }
            if(target != null)
                target.enableClickGuide();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void showDragGuide() {
        if(mHelper == null || mRightViewGroup == null || mRightViewGroup.size() == 0 || (mPicInPicViewGroup != null && mPicInPicViewGroup.size() > 0) || mHelper.isFullScreen() || mHelper.isAnimRunning())
            return;
        int currentIndex = mHelper.getCurrentIndex();
        CameraCardView main = (CameraCardView) findViewWithTag("" + currentIndex);
        CameraCardView target = null;
        int minSpace = 1000;
        int middleHeight = getHeight()/2;
        for(int i=0; i<mRightViewGroup.size(); i++) {
            String tag = mRightViewGroup.get(i);
            CameraCardView item = (CameraCardView) findViewWithTag(tag);
            if(item == null)
                return;
            int[] loc = new int[2];
            item.getLocationInWindow(loc);
            int delta = Math.abs(loc[1] + item.getHeight()/2 - middleHeight);
            if(delta < minSpace) {
                minSpace = delta;
                target = item;
            }
        }
        if(target == null)
            return;
        GuideConstants.showDragGuide((Activity) context, target, main, new OnGuidePerformedListener() {
            @Override
            public void onPerformed(String id) {

            }
        });
    }

    public void silentSideVideo(boolean silent) {
        try {
            int currentIndex = mHelper.getCurrentIndex();
            for (String id : mRightViewGroup) {
                View view = findViewWithTag(id);
                if (view != null) {
                    if (silent)
                        ((CameraCardView) view).soundOff();
                    else {
                        if ("0".equalsIgnoreCase(id)) {
                            boolean enableSound = ((CameraCardView) findViewWithTag(currentIndex + "")).enableSoundSwitch();
                            ((CameraCardView) view).manageSound(enableSound);
                            Utils.Log("VOICE", "...................silentSideVideo");
                            ((CameraCardView) view).managePadding(true, true);
                        } else {
                            ((CameraCardView) view).openSound();
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}